package com.icode.web.startup;

import com.icode.service.user.AdministratorService;
import com.icode.service.user.CustomerService;
import com.icode.web.filter.SiteMeshFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
import org.springframework.web.filter.CharacterEncodingFilter;

import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import java.util.EnumSet;

/**
 * User: alexz
 * Date: 15-1-7
 * Time: 下午4:32
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends AbstractSecurityWebApplicationInitializer {

    @Override
    protected String getDispatcherWebApplicationContextSuffix() {
        return "dispatcher";
    }

    @Override
    protected void afterSpringSecurityFilterChain(ServletContext servletContext) {
        FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("characterEncodingFilter", CharacterEncodingFilter.class);
        encodingFilter.setInitParameter("encoding", "UTF-8");
        encodingFilter.setInitParameter("forceEncoding", "true");
        encodingFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");

        FilterRegistration.Dynamic siteMeshFilter = servletContext.addFilter("siteMeshFilter", SiteMeshFilter.class);
        siteMeshFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new StandardPasswordEncoder("MD5");
    }

    @Configuration
    @Order(1)
    public static class FrontendWebSecurityConfigureAdapter extends WebSecurityConfigurerAdapter {

        @Autowired
        private CustomerService customerService;

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().requestMatchers()
                    .antMatchers("/", "/front/**", "/login/form", "/order/form/*", "/order/*","/front/user_info/**", "/my_house/**","/exchange/**","/logout","/valid/**","/rent/**","/password/update/**","/toAssignmnet/**")
                    .and().exceptionHandling().accessDeniedPage("/deny")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/order/*", "/order/form/*", "/my_house/**","/exchange/**","/front/user_info/**","/valid/**","/rent/**","/password/update/**","/toAssignmnet/**")
                    .access("isAuthenticated() and principal.isCustomer()")
                    .and()
                    .formLogin()
                    .loginPage("/login/form")
                    .permitAll()
                    .defaultSuccessUrl("/")
                    .and()
                    .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/");
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(customerService).passwordEncoder(passwordEncoder);
        }
    }

    @Configuration
    public static class BackendWebSecurityConfigureAdapter extends WebSecurityConfigurerAdapter {

        @Autowired
        private AdministratorService administratorService;

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().requestMatchers()
                    .antMatchers("/logon", "/welcome", "/exit")
                    .and().exceptionHandling().accessDeniedPage("/deny")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/welcome").authenticated()
                    .anyRequest().access("isAuthenticated() and principal.isAdministrator()")
                    .and()
                    .formLogin()
                    .loginPage("/logon")
                    .permitAll()
                    .defaultSuccessUrl("/welcome")
                    .and()
                    .logout()
                    .logoutUrl("/exit")
                    .logoutSuccessUrl("/logon");
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(administratorService).passwordEncoder(passwordEncoder);
        }
    }
}
